﻿using System.Text.RegularExpressions;

namespace Devonline.Core;

/// <summary>
/// 统一社会信用代码, GB32100-2015
/// </summary>
public class UnifiedSocialCreditIdentifier(string code)
{
    /// <summary>
    /// 统一社会信用代码
    /// </summary>
    private readonly string _code = code;
    /// <summary>
    /// // 统一社会信用代码可用字符 不含I、O、S、V、Z
    /// </summary>
    private static readonly string _codeOrigin = "0123456789ABCDEFGHJKLMNPQRTUWXY";
    /// <summary>
    /// 统一社会信用代码相对应顺序的加权因子 
    /// </summary>
    private static readonly int[] _weightedFactors = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28];

    /// <summary>
    /// 18位统一社会信用代码
    /// </summary>
    public bool Validate()
    {
        var pattern = @"^\w\w\d{6}\w{9}\w$";
        if (!Regex.IsMatch(_code, pattern))
        {
            //格式检查
            return false;
        }

        var sum = 0;
        for (int i = 0; i < _code.Length - 1; i++)
        {
            sum += _weightedFactors[i] * _codeOrigin.IndexOf(_code[i]);
        }

        //实际校验位的值
        var logicCheckCode = 31 - sum % 31;
        if (logicCheckCode == 31)
        {
            logicCheckCode = 0;
        }

        logicCheckCode = _codeOrigin[logicCheckCode];
        if (logicCheckCode != char.ToUpperInvariant(_code[17]))
        {
            //校验码验证
            return false;
        }

        //符合GB32100-2015标准
        return true;
    }
}